/** @file shader_prog.h
    @brief Program of shaders */

#ifndef G3_RES_SHADER_PROG_H
#define G3_RES_SHADER_PROG_H

#include "res_shader.h"
#include "res_shader_mgr.h"

namespace G3 {

/** @class SHADER_PROGRAM
    @brief A program that consists of multiple shaders */
class SHADER_PROGRAM {
    friend class MATERIAL;

    public:
        /**
            @brief A constructor
        */
        SHADER_PROGRAM ();
        /**
            @brief A destructor
        */
        ~SHADER_PROGRAM ();

        /**
            @brief Assignment operator
            @param[in] program Reference to the shader program to be copied
            @return Reference to the freshly copied program
        */
        SHADER_PROGRAM& operator=(const SHADER_PROGRAM &program);

        /** Pointer to the log */
        G3::LOG *Log;

        /** Shader program object index */
        uint programObject;
        /** Vertex shaders */
        std::vector<G3::H_VSHADER> vertexShaders;
        /** Pixel shaders */
        std::vector<G3::H_PSHADER> pixelShaders;

        /**
            @brief Attaches a shader to this program
            @param[in] Filename Path to the shader to be loaded
            @param[in] Profile Shader profile \see SHADER_PROFILE
            @return True on success, false on failure
        */
        bool AttachShader (const std::string &Filename, G3::SHADER_PROFILE Profile);
        /**
            @brief Detaches a shader from this program
            @param[in] handle Shader handle
            @return True on success, false on failure
        */
        bool DetachShader (uint handle);
        /**
            @brief Detaches a shader from this program
            @param[in] Filename Path to the shader to be unloaded
            @return True on success, false on failure
            \todo Detach by handle
        */
        bool DetachShader (const std::string &Filename);

        /**
            @brief Gets a pointer to the shader by index
            @param[in] Profile Profile of the shader
            @param[in] index Index among the shaders that match the profile
            @return Pointer to the shader or NULL if the correct shader couldn't be found
        */
        boost::shared_ptr<G3::SHADER_BASE> GetShader (G3::SHADER_PROFILE Profile, int index);

        /**
            @brief Gets a pointer to the shader by filename
            @param[in] name Reference to the filename string
            @return Pointer to the shader or NULL if the correct shader couldn't be found
        */
        boost::shared_ptr<G3::SHADER_BASE> GetShader (const std::string &filename);

        /**
            @brief Applies the shader program
        */
        void Apply ();
        /**
            @brief Unapplies the shader program
        */
        void UnApply ();

        /**
            @brief Links the shaders into a ready-to-execute program
        */
        bool Link ();

    protected:
        /**
            @brief Clears the program
        */
        void Clear ();
};

}

#endif // G3_RES_SHADER_PROG_H
